#lang sicp
(define (inverter input output)
  (define (invert-input)
    (let ((new-signal (logical-not (get-signal input))))
      (after-delay inverter-delay
                   (lambda ()
                     (set-signal! output new-signal)))))
  (add-action! input invert-input)
  'ok)

(define (and-gate i1 i2 output)
  (define (and-action)
    (let ((new-signal (logical-and (get-signal i1)
                                   (get-signal i2))))
      (after-delay and-gate-delay
                   (lambda ()
                     (set-signal! output new-signal)))))
  (add-action! i1 and-action)
  (add-action! i2 and-action)
  'ok)

(define (or-gate i1 i2 o)
  (define (or-action)
    (let ((new-signal (logical-or (get-signal i1)
                                  (get-signal i2))))
      (after-delay or-gate-delay
                   (lambda ()
                     (set-signal! o new-signal)))))
  (add-action! i1 or-action)
  (add-action! i2 or-action)
  'ok)

(define (or-gate1 i1 i2 o)
  (define a (make-wire))
  (define b (make-wire))
  (define c (make-wire))
  (inverter i1 a)
  (inverter i2 b)
  (and-gate a b c)
  (inverter c o))


(define (logical-not s)
  (cond ((= s 1) 0)
        ((= s 0) 1)
        (else
         (error "Invalid signal" s))))

(define (logical-and s1 s2)
  (cond ((and (= s1 1) (= s2 1)) 1)
        ((or (= s1 0) (= s2 0)) 0)
        (else
         (error "Invalid signal" s1 s2))))

(define (logical-or s1 s2)
  (cond ((or (= s1 1) (= s2 1)) 1)
        ((and (= s1 0) (= s2 0)) 0)
        (else
         (error "Invalid signal" s1 s2))))


(define (ripple-carry-adder Ak Bk Sk c)
  (if (null? Ak)
      'ok
      (let ((c-out (make-wire)))
        (full-adder (car Ak) (car Bk) c (car Sk) c-out)
        (ripple-carry-adder (cdr Ak) (cdr Bk) (cdr Sk) c-out))))

(define (full-adder a b c-in sum c-out)
  (let ((s (make-wire))
        (c1 (make-wire))
        (c2 (make-wire)))
    (half-adder b c-in s c1)
    (half-adder a s sum c2)
    (or-gate c1 c2 c-out)
    'ok))


(define (half-adder a b s c)
  (let ((d (make-wire)) (e (make-wire)))
    (or-gate a b d)
    (and-gate a b c)
    (inverter c e)
    (and-gate d e s)
    'ok))


